import time
import threading
from Helper import *
from multiprocessing import shared_memory

memName = "LINConverterSim"

memSetLock = threading.Lock()

class LINPackStruct:
    packCount = 0
    dataBuffer = bytes(1024)
    def toString(self):
        res = hexToStyledStr(self.packCount.to_bytes(4, byteorder='little'))
        res += hexToStyledStr(self.dataBuffer)

class memGetPackageEvent:
    methodHandler = []
    @staticmethod
    def raiseEvent(*args):
        for func in memGetPackageEvent.methodHandler:
            func(*args)

def setMem(data):
    memSetLock.acquire()
    try:
        shm = shared_memory.SharedMemory(name=memName + "_Set", create=True, size=1500)
    except:
        shm = shared_memory.SharedMemory(name=memName + "_Set", size=1500)

    buf = shm.buf
    data_byteArr = structToBytearray(data)
    if data_byteArr == None:
        log("type of data is wrong", ERROR)
        memSetLock.release()
        return None
    buf = memoryview(data_byteArr)
    memSetLock.release()
    log("Send LIN package: " + data.toString(), INFO)

def getMem():
    try:
        shm = shared_memory.SharedMemory(name=memName + "_Get", create=True, size=1500)
    except:
        shm = shared_memory.SharedMemory(name=memName + "_Get", size=1500)

    packageIndex = 0
    while True:
        buf = shm.buf
        recvData = bytesToStruct(buf.tobytes())
        currentIndex = recvData.packCount
        if currentIndex > packageIndex:
            packageIndex = currentIndex
            memGetPackageEvent.raiseEvent(recvData.dataBuffer)
        time.sleep(0.01)

def structToBytearray(struct):
    if type(struct) is not LINPackStruct:
        return None
    res = bytearray()
    res.extend(struct.packCount.to_byte(4, ))
    res.extend(struct.dataBuffer)
    return res

def bytesToStruct(byteData):
    res = LINPackStruct()
    res.packCount = int.from_bytes(byteData[: 4], byteorder='little')
    res.dataBuffer = byteData[4: ]
    return res


